//==============================================================================
/**
 * @file	cb_sys.c
 * @brief	簡単な説明を書く
 * @author	goto
 * @date	2006.04.03(月)
 *
 * ここに色々な解説等を書いてもよい
 *
 */
//==============================================================================
#include "common.h"
#include "poketool/poke_tool.h"
#include "system/procsys.h"
#include "system/snd_tool.h"
#include "system/lib_pack.h"
#include "system/brightness.h"
#include "system/heapdefine.h"
#include "system/touch_subwindow.h"
#include "system/fontproc.h"
#include "system/msgdata.h"
#include "system/arc_util.h"
#include "system/window.h"

#include "system/bmp_menu.h"
#include "system/palanm.h"
#include "system/clact_tool.h"
#include "system/wipe.h"
#include "gflib/strbuf.h"
#include "gflib/msg_print.h"

#include "battle/battle_common.h"
#include "battle/graphic/batt_bg_gs_def.h"
#include "wazaeffect/ball_effect_tool.h"
#include "poketool/pokeicon.h"
#include "pokeanime/p_anm_sys.h"

#include "data/cb_data_def.h"
#include "cb_sys.h"
#include "cb_snd_def.h"

/////////////////////////////////////////////////////////////////////////
//プロトタイプ
static void CustomBallSystemInit(int heap);
static void CustomBallSystemEnd(int heap);
static void CustomBallVramBankSet(GF_BGL_INI *bgl);
static void CustomBallVBlank(void* work);

///////////////////////////////////////////////////////////////////////////
/**
 *	@brief	bc_common領域のロード特殊処理
 *
 *	NitroStaticInitはC言語でスタティックイニシャライザを利用するための
 *	NITROシステムの特殊関数で、1ファイルにつき1つ定義することができます
 *
 *	cb_sys.c は bc_common領域の下位に配置された custom_ball領域に存在します。
 *	NitroStaticInitは custom_ball領域がリンクされる時に
 *	コンストラクタ的に呼び出されるので、
 *	これを利用して bc_common領域を事前ロードしています。
 *
 *	詳細はNitroSDK関数リファレンスの NitroStaticInitの項を参照してください
 */
//////////////////////////////////////////////////////////////////////////
#include <nitro/sinit.h>
#include "system/pm_overlay.h"
#if 1	//PLATINUM_MERGE
FS_EXTERN_OVERLAY(bc_common);
FS_EXTERN_OVERLAY(bc_common2);
static void NitroStaticInit(void)
{
	Overlay_Load(FS_OVERLAY_ID(bc_common), OVERLAY_LOAD_NOT_SYNCHRONIZE);
	Overlay_Load(FS_OVERLAY_ID(bc_common2), OVERLAY_LOAD_NOT_SYNCHRONIZE);
}
#else
FS_EXTERN_OVERLAY(bc_common);

static void NitroStaticInit(void)
{
	Overlay_Load(FS_OVERLAY_ID(bc_common), OVERLAY_LOAD_NOT_SYNCHRONIZE);
}
#endif



//--------------------------------------------------------------
/**
 * @brief	プロック初期化
 *
 * @param	proc
 * @param	seq
 *
 * @retval	static PROC_RESULT
 *
 */
//--------------------------------------------------------------
PROC_RESULT CB_ProcInit(PROC* proc, int* seq)
{
	CB_MAIN_WORK* cbmw;
	CB_PROC_WORK* cbpw;

	//ヒープ状態プッシュ
	HeapStatePush();

	///< ヒープ作成
	sys_CreateHeap(HEAPID_BASE_APP, HEAPID_CUSTOM_BALL, CB_DEF_HEAP_SIZE);

	///< ワーク作成
	cbmw = PROC_AllocWork(proc, sizeof(CB_MAIN_WORK), HEAPID_CUSTOM_BALL);
	memset(cbmw, 0, sizeof(CB_MAIN_WORK));

	//引継ぎワークポインタ取得
	cbpw = PROC_GetParentWork(proc);
	cbmw->cb_pw = cbpw;

	cbmw->handle = ArchiveDataHandleOpen( ARC_PM_EDIT, HEAPID_CUSTOM_BALL );


	//初期データ設定

	//現在のキーモードを取得
	cbmw->key_mode = KeyTouchStatus_CheckTouchOrKey(cbmw->cb_pw->kt_status);

	///< ダミー領域に、タマゴ以外の先頭ポケモン配置
	cbmw->test_pp = PokemonParam_AllocWork(HEAPID_CUSTOM_BALL);

	cbmw->sys.hold	= 0xFF;
	cbmw->page.no	= 0;
//	cbmw->page.max	= (CB_Tool_SealCllectionGet(cbmw->cb_pw->save_data) / CB_DEF_PAGE_ITEMS) + 1;
	{
		int add = 0;
		int num;

#if PL_S0815_080722_FIX
		num = CB_Tool_SealCllectionGet( cbmw->cb_pw->save_data );
		if ( num % CB_DEF_PAGE_ITEMS ){
			add = 1;
		}
#else
		num = (CB_Tool_SealCllectionGet(cbmw->cb_pw->save_data) / CB_DEF_PAGE_ITEMS);
		if ( num % CB_DEF_PAGE_ITEMS ){
			 add = 1;
		}
#endif
		cbmw->page.max	= (CB_Tool_SealCllectionGet(cbmw->cb_pw->save_data) / CB_DEF_PAGE_ITEMS) + add;
	}

	if (cbmw->page.max > CB_DEF_PAGE_MAX){
		cbmw->page.max = CB_DEF_PAGE_MAX;
	}

	cbmw->select[0] = CBProc_SelectPosGet(cbmw->cb_pw);
	cbmw->select[1] = CBProc_SelectPosGet(cbmw->cb_pw);

	///< セーブデータ引継ぎ
	{
		int i;
		int cb_id;
		CB_CORE* core;

		///< アイテムデータ
		cbmw->cb_item_data = CB_SaveData_ItemDataGet(cbmw->cb_pw->save_data);

		///< コアデータ取得
		for (i = 0; i < CB_DEF_CORE_MAX; i++){
			core = CB_SaveData_CoreDataGet(cbmw->cb_pw->save_data, i);
			cbmw->cb_edit_data[i].poke_idx	= CB_DEF_POKE_NOT_INDEX;
			cbmw->cb_edit_data[i].core	 	= core;
		}

		///< 手持ちポケモンがカプセルを持っているか検索
		for (i = 0; i < TEMOTI_POKEMAX; i++){
			if (cbmw->cb_pw->poke_para[i] == NULL){ continue; }

			cb_id = PokeParaGet(cbmw->cb_pw->poke_para[i], ID_PARA_cb_id, 0);
			if (cb_id != 0){
				///< 1 オリジンなので
				cbmw->cb_edit_data[ cb_id - 1 ].poke_idx = i;
			}
		}
	}

	///< 基本初期化
	CustomBallSystemInit(HEAPID_CUSTOM_BALL);

	///< ブレンド
	CB_Tool_DefaultBlendSet();

	cbmw->sys.g3Dman = CB_3D_Init();

	///< 初期化
	cbmw->sys.bgl = GF_BGL_BglIniAlloc(HEAPID_CUSTOM_BALL);
	initVramTransferManagerHeap(CB_DEF_VRAM_TRANSFER_TASK_NUM, HEAPID_CUSTOM_BALL);

	cbmw->sys.pfd = PaletteFadeInit(HEAPID_CUSTOM_BALL);
	PaletteTrans_AutoSet(cbmw->sys.pfd, TRUE);
	PaletteFadeWorkAllocSet(cbmw->sys.pfd, FADE_MAIN_BG,  0x200, HEAPID_CUSTOM_BALL);
	PaletteFadeWorkAllocSet(cbmw->sys.pfd, FADE_SUB_BG,	  0x200, HEAPID_CUSTOM_BALL);
	PaletteFadeWorkAllocSet(cbmw->sys.pfd, FADE_MAIN_OBJ, 0x200, HEAPID_CUSTOM_BALL);
	PaletteFadeWorkAllocSet(cbmw->sys.pfd, FADE_SUB_OBJ,  0x200, HEAPID_CUSTOM_BALL);

	CustomBallVramBankSet(cbmw->sys.bgl);

	CB_Particle_Init();

	///< ソフトスプライト
	cbmw->sys.ssm_p = SoftSpriteInit(HEAPID_CUSTOM_BALL);

	///< アニメ
	cbmw->sys.pas = PokeAnm_AllocMemory(HEAPID_CUSTOM_BALL, 1, 0);

	///< ウィンドウ
	{
		int win_type;

		win_type = CONFIG_GetWindowType(cbmw->cb_pw->cfg);
		CB_BMP_WindowResLoad(cbmw->sys.bgl, cbmw->sys.pfd, win_type);
		CB_BMP_WindowResLoad_Sub(cbmw->sys.bgl, cbmw->sys.pfd, win_type);
	}

	///< OBJ
	CB_Tool_CatsInit(&cbmw->sys);

	///< タッチパネル
	{
		u32 active;
		InitTPSystem();
		active = InitTPNoBuff( 4 );
		if(active != TP_OK){
			OS_Printf("custom ball != TP_OK\n");
		}
	}

	///< ボタンシステム
	CB_Tool_ButtonInit(cbmw);

	sys_VBlankFuncChange(CustomBallVBlank, cbmw);

	///< --- font oam
	FontOam_SysInit(cbmw);

	///< サウンドデータロード(カスタムボール)(BGM引継ぎ)
//	Snd_DataSetByScene( SND_SCENE_SUB_CUSTOM, 0, 0 );

	OS_Printf("□ custom ball init\n");

	return PROC_RES_FINISH;
}


//--------------------------------------------------------------
/**
 * @brief	プロックメイン
 *
 * @param	proc
 * @param	seq
 *
 * @retval	static PROC_RESULT
 *
 */
//--------------------------------------------------------------
enum {
	CB_SEQ_IN = 0,
	CB_SEQ_MAIN,
	CB_SEQ_OUT,
};
PROC_RESULT CB_ProcMain(PROC* proc, int* seq)
{
	CB_MAIN_WORK* cbmw = PROC_GetWork(proc);

	if (!CustomMain_Executed(cbmw)){
		return PROC_RES_FINISH;
	}
	SoftSpriteMain(cbmw->sys.ssm_p);
	CB_Particle_Main();

//	OS_Printf("□ custom ball main\n");

	return PROC_RES_CONTINUE;
}


//--------------------------------------------------------------
/**
 * @brief	プロック終了
 *
 * @param	proc
 * @param	seq
 *
 * @retval	static PROC_RESULT
 *
 */
//--------------------------------------------------------------
PROC_RESULT CB_ProcEnd(PROC* proc, int* seq)
{
	CB_MAIN_WORK* cbmw;

	cbmw = PROC_GetWork(proc);

	GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG0,  VISIBLE_OFF);
	GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG1,  VISIBLE_OFF);
	GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG2,  VISIBLE_OFF);
	GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG3,  VISIBLE_OFF);
	GF_Disp_GXS_VisibleControl(GX_PLANEMASK_BG0, VISIBLE_OFF);
	GF_Disp_GXS_VisibleControl(GX_PLANEMASK_BG1, VISIBLE_OFF);
	GF_Disp_GXS_VisibleControl(GX_PLANEMASK_BG2, VISIBLE_OFF);
	GF_Disp_GXS_VisibleControl(GX_PLANEMASK_BG3, VISIBLE_OFF);
	GF_BGL_BGControlExit(cbmw->sys.bgl, GF_BGL_FRAME1_M);
	GF_BGL_BGControlExit(cbmw->sys.bgl, GF_BGL_FRAME2_M);
	GF_BGL_BGControlExit(cbmw->sys.bgl, GF_BGL_FRAME3_M);
	GF_BGL_BGControlExit(cbmw->sys.bgl, GF_BGL_FRAME0_S);
	GF_BGL_BGControlExit(cbmw->sys.bgl, GF_BGL_FRAME1_S);
	GF_BGL_BGControlExit(cbmw->sys.bgl, GF_BGL_FRAME2_S);
	GF_BGL_BGControlExit(cbmw->sys.bgl, GF_BGL_FRAME3_S);


	sys_FreeMemoryEz(cbmw->sys.bgl);

	PaletteFadeWorkAllocFree(cbmw->sys.pfd, FADE_MAIN_BG);
	PaletteFadeWorkAllocFree(cbmw->sys.pfd, FADE_SUB_BG);
	PaletteFadeWorkAllocFree(cbmw->sys.pfd, FADE_MAIN_OBJ);
	PaletteFadeWorkAllocFree(cbmw->sys.pfd, FADE_SUB_OBJ);
	PaletteFadeFree(cbmw->sys.pfd);

	CBProc_SelectPosSet(cbmw->cb_pw, cbmw->select[0]);

	sys_FreeMemoryEz(cbmw->test_pp);
	CBS_Delete(cbmw);
	BMN_Delete(cbmw->sys.btn);

	///< soft sprite
	SoftSpriteEnd(cbmw->sys.ssm_p);
	PokeAnm_FreeMemory(cbmw->sys.pas);

	///< font oam
	FontOam_SysDelete(cbmw);

	CB_Tool_CatsDelete(&cbmw->sys);

	DellVramTransferManager();


	GF_G3D_Exit(cbmw->sys.g3Dman);

	CustomBallSystemEnd( HEAPID_CUSTOM_BALL );

	ArchiveDataHandleClose( cbmw->handle );

	//現在のキーモードを書き出し
	KeyTouchStatus_SetTouchOrKey(cbmw->cb_pw->kt_status,cbmw->key_mode);

	PROC_FreeWork(proc);	///< cbmw free

	///< タッチパネル
	{
		u32 active;
		active = StopTP();
		if(active != TP_OK){
			OS_Printf("custom ball != TP_OK\n");
		}
	}
	HeapStatePop();
	HeapStateCheck(HEAPID_CUSTOM_BALL);

	sys_DeleteHeap( HEAPID_CUSTOM_BALL );

	Overlay_UnloadID(FS_OVERLAY_ID(bc_common));
#if 1	//PLATINUM_MERGE
	Overlay_UnloadID(FS_OVERLAY_ID(bc_common2));
#endif
	OS_Printf("□ custom ball end\n");

	return PROC_RES_FINISH;
}
/*

	メインシステム

 */

//--------------------------------------------------------------
/**
 * @brief	基本的なシステム初期化
 *
 * @param	heap
 *
 * @retval	none
 *
 */
//--------------------------------------------------------------
static void CustomBallSystemInit(int heap)
{
	sys_VBlankFuncChange(NULL, NULL);	///< VBlankセット
	sys_HBlankIntrStop();				///< HBlank割り込み停止

	GF_Disp_GX_VisibleControlInit();
	GF_Disp_GXS_VisibleControlInit();
	GX_SetVisiblePlane(0);
	GXS_SetVisiblePlane(0);
}


//--------------------------------------------------------------
/**
 * @brief	基本的なシステム破棄
 *
 * @param	heap
 *
 * @retval	none
 *
 */
//--------------------------------------------------------------
static void CustomBallSystemEnd(int heap)
{
	sys_VBlankFuncChange( NULL, NULL );	///< VBlankセット
	sys_HBlankIntrStop();				///< HBlank割り込み停止
}


//--------------------------------------------------------------
/**
 * @brief	Vram設定
 *
 * @param	bgl
 *
 * @retval	none
 *
 */
//--------------------------------------------------------------
static void CustomBallVramBankSet(GF_BGL_INI *bgl)
{
	GF_Disp_GX_VisibleControlInit();

	//VRAM設定
	{
		GF_BGL_DISPVRAM vramSetTable = {
			GX_VRAM_BG_128_A,				// メイン2DエンジンのBG
			GX_VRAM_BGEXTPLTT_NONE,			// メイン2DエンジンのBG拡張パレット
			GX_VRAM_SUB_BG_32_H,			// サブ2DエンジンのBG
			GX_VRAM_SUB_BGEXTPLTT_NONE,		// サブ2DエンジンのBG拡張パレット
			GX_VRAM_OBJ_64_E,				// メイン2DエンジンのOBJ
			GX_VRAM_OBJEXTPLTT_NONE,		// メイン2DエンジンのOBJ拡張パレット
			GX_VRAM_SUB_OBJ_16_I,			// サブ2DエンジンのOBJ
			GX_VRAM_SUB_OBJEXTPLTT_NONE,	// サブ2DエンジンのOBJ拡張パレット
			GX_VRAM_TEX_01_BC,				// テクスチャイメージスロット
			GX_VRAM_TEXPLTT_01_FG			// テクスチャパレットスロット
		};
		GF_Disp_SetBank( &vramSetTable );

		//VRAMクリア
		MI_CpuClear32((void*)HW_BG_VRAM, HW_BG_VRAM_SIZE);
		MI_CpuClear32((void*)HW_DB_BG_VRAM, HW_DB_BG_VRAM_SIZE);
		MI_CpuClear32((void*)HW_OBJ_VRAM, HW_OBJ_VRAM_SIZE);
		MI_CpuClear32((void*)HW_DB_OBJ_VRAM, HW_DB_OBJ_VRAM_SIZE);
	}

	// BG SYSTEM
	{
		GF_BGL_SYS_HEADER BGsys_data = {
			GX_DISPMODE_GRAPHICS, GX_BGMODE_0, GX_BGMODE_0, GX_BG0_AS_3D,
		};
		GF_BGL_InitBG( &BGsys_data );
	}

	//メイン画面フレーム設定
	{
		GF_BGL_BGCNT_HEADER TextBgCntDat[] = {
			///<FRAME1_M
			{
				0, 0, 0x0800, 0, GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x0000, GX_BG_CHARBASE_0x04000, GX_BG_EXTPLTT_01,
				CB_BG_PRI_SCR_STRING, 0, 0, FALSE
			},
			///<FRAME2_M
			{
				0, 0, 0x2000, 0, GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x1000, GX_BG_CHARBASE_0x0c000, GX_BG_EXTPLTT_01,
				CB_BG_PRI_SCR_SELECT, 0, 0, FALSE
			},
			///<FRAME3_M
			{
				0, 0, 0x1000, 0, GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x3000, GX_BG_CHARBASE_0x10000, GX_BG_EXTPLTT_01,
				CB_BG_PRI_SCR_FIELD, 0, 0, FALSE
			},
		};
		GF_BGL_BGControlSet(bgl, GF_BGL_FRAME1_M, &TextBgCntDat[0], GF_BGL_MODE_TEXT );
		GF_BGL_BGControlSet(bgl, GF_BGL_FRAME2_M, &TextBgCntDat[1], GF_BGL_MODE_TEXT );
		GF_BGL_BGControlSet(bgl, GF_BGL_FRAME3_M, &TextBgCntDat[2], GF_BGL_MODE_TEXT );
		GF_BGL_ScrClear(bgl, GF_BGL_FRAME1_M );
		GF_BGL_ScrClear(bgl, GF_BGL_FRAME2_M );
		GF_BGL_ScrClear(bgl, GF_BGL_FRAME3_M );

		G2_SetBG0Priority(BATTLE_3DBG_PRIORITY);
		GF_Disp_GX_VisibleControl(GX_PLANEMASK_BG0, VISIBLE_ON);
	}

	///< サブ画面フレーム設定
	{
		GF_BGL_BGCNT_HEADER TextBgCntDat[] = {
			{	/// font
				0, 0, 0x800, 0, GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x6800, GX_BG_CHARBASE_0x00000, GX_BG_EXTPLTT_01,
				CB_BG_PRI_SCR_SUB_STRING, 0, 0, FALSE
			},
			{	/// boal
				0, 0, 0x800, 0, GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x7000, GX_BG_CHARBASE_0x04000, GX_BG_EXTPLTT_01,
				CB_BG_PRI_SCR_BALL, 0, 0, FALSE
			},
			{	/// list
				0, 0, 0x800, 0, GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x6000, GX_BG_CHARBASE_0x00000, GX_BG_EXTPLTT_01,
				CB_BG_PRI_SCR_LIST, 0, 0, FALSE
			},
			{	/// edit
				0, 0, 0x800, 0, GF_BGL_SCRSIZ_256x256, GX_BG_COLORMODE_16,
				GX_BG_SCRBASE_0x7800, GX_BG_CHARBASE_0x04000, GX_BG_EXTPLTT_01,
				CB_BG_PRI_SCR_EDIT, 0, 0, FALSE
			},
		};
		GF_BGL_BGControlSet(bgl, GF_BGL_FRAME0_S, &TextBgCntDat[0], GF_BGL_MODE_TEXT);
		GF_BGL_BGControlSet(bgl, GF_BGL_FRAME1_S, &TextBgCntDat[1], GF_BGL_MODE_TEXT);
		GF_BGL_BGControlSet(bgl, GF_BGL_FRAME2_S, &TextBgCntDat[2], GF_BGL_MODE_TEXT);
		GF_BGL_BGControlSet(bgl, GF_BGL_FRAME3_S, &TextBgCntDat[3], GF_BGL_MODE_TEXT);
		GF_BGL_ScrClear(bgl, GF_BGL_FRAME0_S);
		GF_BGL_ScrClear(bgl, GF_BGL_FRAME1_S);
		GF_BGL_ScrClear(bgl, GF_BGL_FRAME2_S);
		GF_BGL_ScrClear(bgl, GF_BGL_FRAME3_S);
		GF_Disp_GXS_VisibleControl(CB_PLANE_LIST, VISIBLE_OFF);
	}
}

static void CustomBallVBlank(void* work)
{
	CB_MAIN_WORK* wk = work;

	SoftSpriteTextureTrans(wk->sys.ssm_p);

	CATS_RenderOamTrans();
	PaletteFadeTrans(wk->sys.pfd);

	GF_BGL_VBlankFunc(wk->sys.bgl);
	DoVramTransferManager();			///< Vram転送マネージャー実行

	OS_SetIrqCheckFlag(OS_IE_V_BLANK);
}

// =============================================================================
//
//
//	■ PROCワークへのアクセス関数
//
//
// =============================================================================
///< ポケモンパラメータ
POKEMON_PARAM* CBProc_PokeParaGet(CB_PROC_WORK* pw, int no)
{
	int idx = no;

	if (pw->poke_cnt < idx){
		GF_ASSERT(0);
		idx = 0;
	}

	return pw->poke_para[ idx ];
}

///< 最後に選択していたカーソル位置
u8 CBProc_SelectPosGet(CB_PROC_WORK* pw)
{
	return pw->select_pos;
}

void CBProc_SelectPosSet(CB_PROC_WORK* pw, u8 pos)
{
	pw->select_pos = pos;
}


///< プロックの次のシーケンス
u8 CBProc_NextModeGet(CB_PROC_WORK* pw)
{
	return pw->proc_next_mode;
}

/**
 *	@brief	ブロックの次のシーケンスを設定
 */
void CBProc_NextModeSet(CB_PROC_WORK* pw, u8 mode)
{
	pw->proc_next_mode = mode;
}

